home *** CD-ROM | disk | FTP | other *** search
- ;;; hier-mode.el
- ;;; Hierarchy mode (for hierarchies output by hier++)
-
- ;;; See the docstring for defun hier-mode for a description.
-
- ;;; Copyright (C) 1993, Intellection Inc.
- ;;;
- ;;; Author: Brian M Kennedy (kennedy@intellection.com)
- ;;;
- ;;; This program is free software; you can redistribute it and/or modify
- ;;; it under the terms of the GNU General Public License as published by
- ;;; the Free Software Foundation; either version 1, or (at your option)
- ;;; any later version.
- ;;;
- ;;; This program is distributed in the hope that it will be useful,
- ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;;; GNU General Public License for more details.
- ;;;
- ;;; A copy of the GNU General Public License can be obtained from the
- ;;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;;; 92/08 Brian M Kennedy Added direct access commands; added sort to member list
- ;;; 92/06 Brian M Kennedy Original
- ;;; (using other GNU Emacs modes as a template)
-
- ;;; Ideally, this mode should be rewritten based on outline.el, by simply setting
- ;;; a few of outline.el's variables. That would provide additional functionality
- ;;; such as hide/show. But to do it right, you should modify the other functions
- ;;; in this file to auto-show things being searched for (otherwise, hiding would
- ;;; be more a hindrance than a help).
-
- (provide 'hier-mode)
-
- (autoload 'visit-tags-table-buffer "tags")
- (autoload 'prompt-for-tag "tags")
-
-
- (defvar hier-mode-syntax-table nil
- "Syntax table used while in hier mode.")
- (if hier-mode-syntax-table
- ()
- (setq hier-mode-syntax-table (make-syntax-table))
- )
-
- (defvar hier-mode-abbrev-table nil
- "Abbrev table used while in bib mode.")
- (define-abbrev-table 'hier-mode-abbrev-table ())
-
- (defvar hier-mode-map nil "")
- (if hier-mode-map
- ()
- (setq hier-mode-map (make-sparse-keymap))
- (define-key hier-mode-map "\M-h" 'hier-find)
- (define-key hier-mode-map "\M-g" 'hier-find-again)
- (define-key hier-mode-map "\M-m" 'hier-show-members)
- (define-key hier-mode-map "\M-p" 'hier-previous-element)
- (define-key hier-mode-map "\M-n" 'hier-next-element)
- (define-key hier-mode-map "\M-u" 'hier-upto-parent)
- )
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defun hier-mode ()
- "Major mode for viewing class hierarchy files output by hier++.
- The file is formatted like this:
-
- * class_a
- * child_b :class_a
- * child_c :class_a :class_f
- * grandchild_d :child_c
- * grandchild_e :child_c
- * class_f
- * child_c :class_a :class_f
- * grandchild_d :child_c
- * grandchild_e :child_c
- * child_g :class_f
-
- Classes child_b and child_c are derived from class_a; classes child_c and
- child_g are derived from class_f; classes grandchild_d and grandchild_e are
- both derived from child_c. Note that each class (and all of its children)
- will appear in the file once under each parent.
-
- Defined keys:
- M-p moves to the previous sibling
- M-n moves to the next sibling
- M-u moves up to the parent
- M-h finds the first occurrence of the hierarchy element for a class
- (similar to M-. in behavior)
- M-g finds the next occurrence (like M-,) in the case of multiple-inheritance.
- M-m brings up a new window with a listing of all the members (both direct and
- inherited) of that hierarchy entry. It does this via tags, so you must
- have tags set up in Emacs. It will also only work properly if the tags
- file was generated by etags++ (companion to hier++)."
- (interactive)
- (kill-all-local-variables)
- (use-local-map hier-mode-map)
- (setq mode-name "Hierarchy")
- (setq major-mode 'hier-mode)
- (setq local-abbrev-table hier-mode-abbrev-table)
- (set-syntax-table hier-mode-syntax-table)
- ;(run-hooks 'hier-mode-hook)
- )
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Find hierarchy elements
-
- ;; Return a default name to search for, based on the text at point.
- (defun hier-find-default ()
- (save-excursion
- (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (if (re-search-backward "\\sw\\|\\s_" nil t)
- (progn (forward-char 1)
- (buffer-substring (point)
- (progn (forward-sexp -1)
- (while (looking-at "\\s'")
- (forward-char 1))
- (point))))
- nil)))
-
- (defun hier-find-element (string)
- (let* ((default (hier-find-default))
- (spec (read-string
- (if default
- (format "%s(default %s) " string default)
- string))))
- (list (if (equal spec "")
- default
- spec))))
-
- (defvar hier-last-find-element nil
- "The last element searched for by hier-find.")
-
- (defun hier-find (element)
- (interactive (hier-find-element "Find element: "))
- (setq hier-last-find-element (concat "* " element " "))
- (goto-char (point-min))
- (hier-find-again)
- )
-
- (defun hier-find-again ()
- (interactive)
- (if hier-last-find-element
- (search-forward hier-last-find-element)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Cursor movement through hierarchy
-
- (defun hier-previous-element (ignore)
- "Goto previous hierarchy element at this level or higher."
- (interactive "p")
- (back-to-indentation)
- (let ((indent (current-indentation)))
- (previous-line 1)
- (while (< indent (current-indentation))
- (previous-line 1) ))
- (back-to-indentation) )
-
- (defun hier-next-element (ignore)
- "Goto next hierarchy element at this level or higher."
- (interactive "p")
- (back-to-indentation)
- (let ((indent (current-indentation)))
- (next-line 1)
- (while (< indent (current-indentation))
- (next-line 1) ))
- (back-to-indentation) )
-
- (defun hier-upto-parent (arg)
- "Goto the parent hierarchy element."
- (interactive "p")
- (let ((indent (current-indentation)))
- (if (> indent 0)
- (while (<= indent (current-indentation))
- (forward-line -1) )))
- (back-to-indentation) )
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Find Class Members
-
- (defun hier-regexp-list (&optional re-list)
- (end-of-line)
- (let ((eol (point)))
- (back-to-indentation)
- (forward-char 2)
- (let ((re (concat "\C-a"
- (buffer-substring (point) (progn (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (point) ))
- "::")))
- (setq re-list (cons re re-list))
- (forward-word 1)
- (while (<= (point) eol)
- (forward-word -1)
- (let ((start (point))
- (end (progn (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (point) )) )
- (save-excursion
- (hier-find (buffer-substring start end))
- (setq re-list (hier-regexp-list re-list)) ))
- (forward-word 1) )
- re-list)))
-
-
- (defvar hier-members-column 30
- "Column to line up member names in *Members List* buffer.")
-
- (defun hier-members-apropos (name re-list &optional data-members-only-p)
- "Display list of all tags in tag table that regexp matches."
- (save-excursion
- (with-output-to-temp-buffer "*Members List*"
- (if data-members-only-p
- (princ "== Data Members of Class ")
- (princ "== All Members of Class "))
- (prin1 name)
- (princ " ==")
- (terpri)
- (visit-tags-table-buffer)
- (while re-list
- (goto-char 1)
- (while (re-search-forward (car re-list) nil t)
- (skip-chars-backward "^\C-a")
- (princ (buffer-substring (point)
- (progn (end-of-line)
- (point))))
- (terpri)
- (forward-line 1) )
- (setq re-list (cdr re-list)) ))
- (set-buffer "*Members List*")
- ;; Remove Non-Data Members?
- (if data-members-only-p
- ;; remove lines not ending in "_" or "=" (title line)
- (progn (goto-char (point-max))
- (while (not (bobp))
- (forward-char -2)
- (if (not (looking-at "[_=]"))
- (progn (forward-char 2)
- (delete-region (point) (progn (forward-line -1) (point))))
- (forward-line -1)))))
- ;; Sort Buffer
- (goto-line 2)
- (sort-regexp-fields nil "^.*$" "::[^:\n]*$" (point) (point-max))
- ;; Remove Duplicate Entries
- (goto-line 2)
- (while (not (save-excursion (forward-line 1) (eobp)))
- (if (string-equal (buffer-substring (point) (progn (forward-line 1) (point)))
- (buffer-substring (point) (progn (forward-line 1) (point))))
- (delete-region (point) (progn (forward-line -1) (point))) )
- (forward-line -1) )
- ;; Line Up Colons
- (goto-char (point-min))
- (while (search-forward "::" nil t)
- (let ((indent (- hier-members-column (current-column))))
- (if (> indent 0)
- (progn (beginning-of-line)
- (indent-to-column indent) )))
- (forward-line 1) )
- ))
-
-
- (defun hier-show-members (&optional data-members-only-p)
- "Show the members, both direct and inherited, of this hierarchy element."
- (interactive)
- (save-excursion
- (back-to-indentation)
- (forward-char 2)
- (let ((name (buffer-substring (point) (progn (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (point) ))) )
- (hier-members-apropos name (hier-regexp-list) data-members-only-p) )))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Auxiliary Functions
-
- (defun hier-base-list ()
- "Returns a list of the names of all the direct base classes on the current line."
- (save-excursion
- (end-of-line)
- (let ((base-list nil)
- (eol (point)))
- (back-to-indentation)
- (forward-char 2)
- (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (forward-word 1)
- (while (<= (point) eol)
- (forward-word -1)
- (setq base-list (cons (buffer-substring (point)
- (progn (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (point) ))
- base-list))
- (forward-word 1) )
- base-list) ) )
-
-
- (defun hier-derived-list ()
- "Returns a list of the names of all the directly derived classes
- from the one on the current line."
- (save-excursion
- (let ((derived-list nil)
- (indent (current-indentation)))
- (next-line 1)
- (back-to-indentation)
- (while (< indent (current-indentation))
- (forward-char 2)
- (setq derived-list (cons (buffer-substring (point)
- (progn (while (looking-at "\\sw\\|\\s_")
- (forward-char 1))
- (point) ))
- derived-list))
- (hier-next-element 1) )
- derived-list) ) )
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; External Functions
-
- (defvar hier-file-name nil
- "The filename in which to find the class hierarchy generated by hier++.")
-
- (defun prompt-for-hier-file-name ()
- "Get hier-file-name from user."
- (setq hier-file-name
- (read-file-name "File containing class hierarchy [typically CLASS.hier]: ")))
-
- (defun class-hierarchy (class-name)
- "Display the hierarchy for the given class. M-g for next occurrence."
- (interactive (list (prompt-for-tag "Display hierarchy for class: ")))
- (if (not hier-file-name)
- (prompt-for-hier-file-name))
- (find-file-other-window hier-file-name)
- (hier-find class-name))
-
- (defun class-members (class-name)
- "Display all members for the given class."
- (interactive (list (prompt-for-tag "Display all members for class: ")))
- (save-excursion
- (set-buffer (find-file-noselect hier-file-name))
- (hier-find class-name)
- (hier-show-members) ))
-
- (defun class-data-members (class-name)
- "Display the data members for the given class."
- (interactive (list (prompt-for-tag "Display data members for class: ")))
- (save-excursion
- (set-buffer (find-file-noselect hier-file-name))
- (hier-find class-name)
- (hier-show-members t) ))
-